package persistencia.repositorio;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.hibernate.ejb.EntityManagerFactoryImpl;
import org.hibernate.ejb.EntityManagerImpl;
import entidade.Funcionario;
import persistencia.unidadepersistencia.UnidadePersistencia;

public class RepositorioFuncionario{

	//Instância da classe 
	public static RepositorioFuncionario instanceRepositorioFuncionario;
	//Instância do Gerenciador de entidades
	private EntityManager em = UnidadePersistencia.getInstanceUnidadePersistencia().getEntityManager();
	//Atributo secao será usado para fazer busca com o criteria
	private Session secao;
	
	//Método para obter a instância da classe
	public static RepositorioFuncionario getInstanceRepositorioFuncionario(){
		
		if(instanceRepositorioFuncionario == null){
			instanceRepositorioFuncionario = new RepositorioFuncionario();
		}
		return instanceRepositorioFuncionario;
	}

	//Método para obter uma Session
	private Session getSession(){
		
		if(em.getDelegate() instanceof EntityManagerFactoryImpl){
			EntityManagerImpl emi = (EntityManagerImpl) em.getDelegate();
			secao = emi.getSession();
		}else{
			secao = (Session) em.getDelegate();
		}
		return secao;		
	}
	
	/**
	 * Método responsável por realizar inserção de um novo funcionário no banco de dados
	 * @param novoFuncionario Instância do novo funcionário a ser inserido
	 */
	public void novo(Funcionario novoFuncionario) {
		em.getTransaction().begin();
		em.persist(novoFuncionario);	
		em.getTransaction().commit();		
	}

	/**
	 * Método responsável por remover um funcionário no banco de dados
	 * @param funcionarioARemover Instância do funcionário que será removido
	 */
	public void remover(Funcionario funcionarioARemover){
		em.getTransaction().begin();
		em.remove(funcionarioARemover);
		em.getTransaction().commit();
	}
	
	/**
	 * Método para atualizar um funcionário depois do mesmo ter sido alterado
	 * @param funcionarioAAtualizar Instância do funcionário a ser atualizado
	 */
	public void atualizar(Funcionario funcionarioAAtualizar){
		em.getTransaction().begin();
		em.merge(funcionarioAAtualizar);
		em.getTransaction().commit();
	}
	
	/**
	 * Método para fazer busca de um funcionário através de seu id
	 * @param id Id a ser pesquisado
	 * @return funcionario Funcionário encontrado
	 */
	public Funcionario buscarId(Integer id){
		
		em.getTransaction().begin();		
		Funcionario f = em.getReference(Funcionario.class, id);
		em.getTransaction().commit();
		return f;
	}
	
	/**
	 * Método para fazer busca de funcionários através de seu nome 
	 * @param nome Nome do funcionário a ser pesquisado
	 * @return List<Funcionario> Lista de Funcionários com esse nome ou parte dele
	 */
	public List<Funcionario> buscarNome(String nome){ 
		Criteria cri = getSession().createCriteria(Funcionario.class);
		cri.add(Restrictions.like("nomeFuncionario", "%"+nome+"%"));
		List<Funcionario> lista = cri.list();
		return lista;
	} 
	
	/**
	 * Método para fazer busca de funcionários através de seu cpf
	 * @param cpf CPF do funcionário a ser pesquisado
	 * @return List<Funcionario> Lista com o funcionário deste cpf ou vários com parte dele(caso não seja digitado todos os dígitos)
	 */
	public List<Funcionario> buscarCPF(String cpf){
		Criteria cri = getSession().createCriteria(Funcionario.class);
		cri.add(Restrictions.eq("cpfFuncionario", cpf));
		List<Funcionario> lista = cri.list();
		return lista;
	}
	
	/**
	 * Método para buscar todos os funcionários cadastrados no banco de dados 
	 * @return List<Funcionario> Lista de todos os funcionários cadastrados no banco de dados
	 */
	public List<Funcionario> listarTodos(){
		CriteriaBuilder builder = em.getCriteriaBuilder();
		CriteriaQuery<Funcionario> criteria = builder.createQuery(Funcionario.class);
		criteria.from(Funcionario.class);
		return em.createQuery(criteria).getResultList();
	}	
}